﻿#region Licence
// <copyright file="Core/ParametersViewModel.cs" company="Kopigi">
// Copyright © Kopigi 2014
// </copyright>
// ****************************************************************************
// <author>Marc PLESSIS</author>
// <date>11/10/2014</date>
// <project>Nentang.wpf</project>
// <web>http://nentang.codeplex.com</web>
// <license>
// The MIT License (MIT)
// 
// Copyright (c) 2013 Marc Plessis
// 
// Permission is hereby granted, free of charge, to any person obtaining a copy of this software and associated documentation files (the "Software"), to deal in the Software without restriction, including without limitation the rights to use, copy, modify, merge, publish, distribute, sublicense, and/or sell copies of the Software, and to permit persons to whom the Software is furnished to do so, subject to the following conditions:
// 
// The above copyright notice and this permission notice shall be included in all copies or substantial portions of the Software.
// 
// THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
// 
// </license>
#endregion
#region using

using System.Collections.Generic;
using System.Collections.ObjectModel;
using System.Linq;
using Core.Class;
using Core.Enums;
using Core.ViewModel.Controls;
using Database.DAL;
using Database.POCO;
using GalaSoft.MvvmLight.CommandWpf;
using Helpers;
using Interfaces.Contracts;
using Interfaces.Enums;

#endregion

namespace Core.ViewModel
{
    /// <summary>
    /// Gestion de paramétres
    /// </summary>
    public class ParametersViewModel : ViewModelBaseCore
    {
        #region fields

        /// <summary>
        /// Indique la largeur des fenêtres pour les utilisateurs et les groupes
        /// </summary>
        private const int WidthChildUserGroupe = 1200;

        #endregion

        #region properties

        /// <summary>
        /// Paramétres utilisateur
        /// </summary>
        private Collection<ParameterModule> _paramsUserModules;
        public Collection<ParameterModule> ParamsUserModules
        {
            get { return _paramsUserModules; }
            set
            {
                _paramsUserModules = value;
                RaisePropertyChanged(() => ParamsUserModules);
            }
        }

        /// <summary>
        /// 
        /// </summary>
        private Collection<ParameterModule> _paramsSystemModules;
        public Collection<ParameterModule> ParamsSystemModules
        {
            get { return _paramsSystemModules; }
            set
            {
                _paramsSystemModules = value;
                RaisePropertyChanged(() => ParamsSystemModules);
            }
        }

        /// <summary>
        /// 
        /// </summary>
        private List<SysUtilisateur> _utilisateurs;
        public List<SysUtilisateur> Utilisateurs
        {
            get { return _utilisateurs; }
            set
            {
                _utilisateurs = value;
                RaisePropertyChanged(() => Utilisateurs);
            }
        }

        /// <summary>
        /// 
        /// </summary>
        private SysUtilisateur _selectedUtilisateur;
        public SysUtilisateur SelectedUtilisateur
        {
            get { return _selectedUtilisateur; }
            set
            {
                _selectedUtilisateur = value;
                if (value != null)
                {
                    ChildWindowService.OpenNewChildWindow(new SysUtilisateurViewModel(value), LocalizedService.LocalizedFromKey("Utilisateur_WindowTitle"), WidthChildUserGroupe, TypeModulesEnum.Core, OnCloseUser);
                }
                RaisePropertyChanged(() => SelectedUtilisateur);
            }
        }

        /// <summary>
        /// 
        /// </summary>
        private List<SysGroupe> _groupes;
        public List<SysGroupe> Groupes
        {
            get { return _groupes; }
            set
            {
                _groupes = value;
                RaisePropertyChanged(() => Groupes);
            }
        }

        /// <summary>
        /// 
        /// </summary>
        private SysGroupe _selectedGroupe;
        public SysGroupe SelectedGroupe
        {
            get { return _selectedGroupe; }
            set
            {
                _selectedGroupe = value;
                if (value != null)
                {
                    ChildWindowService.OpenNewChildWindow(new SysGroupeViewModel(value), LocalizedService.LocalizedFromKey("Groupe_WindowTitle"), WidthChildUserGroupe, TypeModulesEnum.Core, OnCloseGroupe);
                }
                RaisePropertyChanged(() => SelectedGroupe);
            }
        }

        /// <summary>
        /// Liste des thémes
        /// </summary>
        private List<ThemeChoice> _themes;
        public List<ThemeChoice> Themes
        {
            get { return _themes; }
            set
            {
                _themes = value;
                RaisePropertyChanged(() => Themes);
            }
        }

        /// <summary>
        /// Théme choisi
        /// </summary>
        private ThemeChoice _selectedTheme;
        public ThemeChoice SelectedTheme
        {
            get { return _selectedTheme; }
            set
            {
                _selectedTheme = value;
                if (value != null)
                {
                    Core.Properties.Settings.Default.ThemeActual = (int) value.Theme;
                    Core.Properties.Settings.Default.Save();
                }
                RaisePropertyChanged(() => SelectedTheme);
            }
        }

        /// <summary>
        /// List des couleurs d'accentuation
        /// </summary>
        private List<AccentColorChoice> _accentColors;
        public List<AccentColorChoice> AccentColors
        {
            get { return _accentColors; }
            set
            {
                _accentColors = value;
                RaisePropertyChanged(() => AccentColors);
            }
        }

        /// <summary>
        /// Couleur d'accentuation choisie
        /// </summary>
        private AccentColorChoice _selectedAccentColor;
        public AccentColorChoice SelectedAccentColor
        {
            get { return _selectedAccentColor; }
            set
            {
                _selectedAccentColor = value;
                if (value != null)
                {
                    Core.Properties.Settings.Default.AccentColorActual = ColorsHelper.ColorToHex(value.AccentColor);
                    Core.Properties.Settings.Default.Save();
                }
                RaisePropertyChanged(() => SelectedAccentColor);
            }
        }

        public RelayCommand<SysUtilisateur> DeleteUserCommand { get; set; }
        public RelayCommand AddUserCommand { get; set; }
        public RelayCommand<SysGroupe> DeleteGroupeCommand { get; set; }
        public RelayCommand AddGroupeCommand { get; set; }
        public RelayCommand SaveAndCloseCommand { get; set; }
        public RelayCommand<ParameterLight> InitDefaultCommand { get; set; }
        #endregion

        /// <summary>
        /// 
        /// </summary>
        public ParametersViewModel()
        {
            DeleteUserCommand = new RelayCommand<SysUtilisateur>(DeleteUser);
            AddUserCommand = new RelayCommand(AddUser);
            DeleteGroupeCommand = new RelayCommand<SysGroupe>(DeleteGroupe);
            AddGroupeCommand = new RelayCommand(AddGroupe);
            SaveAndCloseCommand = new RelayCommand(SaveAndClose);
            InitDefaultCommand = new RelayCommand<ParameterLight>(InitByDefault);

            LoadParamsUser();
            LoadParamsSystem();    
            LoadUsers();
            LoadGroupes();

            //Thémes
            Themes = ThemeManager.GetThemes();
            SelectedTheme = ThemeManager.ActualTheme;

            //Couleur d'accentuation
            AccentColors = ThemeManager.GetAccentColors();
            SelectedAccentColor = ThemeManager.ActualAccentColor;
        }

        #region event

        private void OnCloseGroupe()
        {
            SelectedGroupe = null;
            LoadGroupes();
        }

        private void OnCloseUser()
        {
            SelectedUtilisateur = null;
            LoadUsers();
        }

        private void OnAnswerDeleteUser(AnswerQuestionMessageEnum arg1, object[] arg2)
        {
            try
            {
                if (arg1 == AnswerQuestionMessageEnum.Yes)
                {
                    if (arg2[0] != null)
                    {
                        var user = (SysUtilisateur) arg2[0];

                        //On commence par supprimer les tables associées
                        DatabaseService.Service.Delete<SysParametresUtilisateur>(p => p.Utilisateur.ID == user.ID, true);
                        DatabaseService.Service.Delete<SysReferentGroupe>(r => r.Referent.ID == user.ID, true);
                        DatabaseService.Service.Delete<SysUtilisateurDroitFonction>(d => d.Utilisateur.ID == user.ID,
                            true);
                        DatabaseService.Service.Delete<SysUtilisateurDroitColonnes>(d => d.Utilisateur.ID == user.ID,
                            true);
                        DatabaseService.Service.Delete<SysNotificationUser>(n => n.Utilisateur.ID == user.ID, true);

                        DatabaseService.Service.Delete<SysUtilisateur>(user, true);
                        LoadUsers();
                    }
                }
            }
            catch (DatabaseSaveException e)
            {
                LoggerService.LogFatalError(LocalizedService.LocalizedFromKey("Parameter_DeleteUserError"), e);
            }
        }

        private void OnAnswerDeleteGroupe(AnswerQuestionMessageEnum arg1, object[] arg2)
        {
            try
            {
                if (arg1 == AnswerQuestionMessageEnum.Yes)
                {
                    if (arg2[0] != null)
                    {
                        var groupe = (SysGroupe)arg2[0];

                        //On commence par supprimer les tables associées
                        DatabaseService.Service.Delete<SysReferentGroupe>(r => r.Groupe.ID == groupe.ID, true);

                        DatabaseService.Service.Delete<SysGroupe>(groupe, true);
                        LoadGroupes();
                    }
                }
            }
            catch (DatabaseSaveException e)
            {
                LoggerService.LogFatalError(LocalizedService.LocalizedFromKey("Parameter_DeleteGroupeError"), e);
            }
        }

        #endregion       

        #region relaycommand

        private void AddGroupe()
        {
            ChildWindowService.OpenNewChildWindow(new SysGroupeViewModel(), LocalizedService.LocalizedFromKey("Groupe_WindowTitle"), WidthChildUserGroupe, TypeModulesEnum.Core, OnCloseGroupe);
        }

        private void DeleteGroupe(SysGroupe obj)
        {
            ChildWindowService.QuestionMessage(string.Format(LocalizedService.LocalizedFromKey("Parameter_DeleteGroupeMessage"), obj.Code), LocalizedService.LocalizedFromKey("MainCoreTitle"), OnAnswerDeleteGroupe, obj);
        }

        private void AddUser()
        {
            ChildWindowService.OpenNewChildWindow(new SysUtilisateurViewModel(), LocalizedService.LocalizedFromKey("Utilisateur_WindowTitle"), WidthChildUserGroupe, TypeModulesEnum.Core, OnCloseUser);
        }

        private void DeleteUser(SysUtilisateur obj)
        {
            ChildWindowService.QuestionMessage(string.Format(LocalizedService.LocalizedFromKey("Parameter_DeleteUserMessage"), obj), LocalizedService.LocalizedFromKey("MainCoreTitle"), OnAnswerDeleteUser, obj);
        }

        private void InitByDefault(ParameterLight parameterLight)
        {
            parameterLight.Valeur = ParametreService.GetValueParameter<string>(parameterLight.Index,
                parameterLight.Module, true);
        }

        private void SaveAndClose()
        {
            //Sauvegarde des paramètres
            var paramsToSave = new List<ParameterLight>();
            if (ParamsUserModules.Any())
            {
                foreach (var paramsToAdd in ParamsUserModules.Select(p => p.Parameters))
                {
                    paramsToSave.AddRange(paramsToAdd);
                }
            }

            if (ParamsSystemModules != null && ParamsSystemModules.Any())
            {
                foreach (var paramsToAdd in ParamsSystemModules.Select(p => p.Parameters))
                {
                    paramsToSave.AddRange(paramsToAdd);
                }
            }

            foreach (var parameter in paramsToSave)
            {
                ParametreService.SetValueParameter(parameter.Index, parameter.Valeur, parameter.Module);
            }

            //Retour à l'accueil
            NavigationService.NavigateTo<AccueilViewModel>(new object[] { }, "RefreshDatas", new object[]{});
        }

        #endregion

        #region private

        /// <summary>
        /// Charge les paramètres utilisateur
        /// </summary>
        private void LoadParamsUser()
        {
            ParamsUserModules = new Collection<ParameterModule>();

            //On ajoute systématiquement le module Core pour le général
            var parametersGen = DatabaseService.Service.Where<SysParametres>(p => p.IsParamUser && p.ExcludedToConfiguration == false && p.Module == (int)TypeModulesEnum.Core).ToList();
            if (parametersGen.Any())
            {
                var paramUser = new ParameterModule { Header = ModulesHelper.LocalizeModule(TypeModulesEnum.Core), Parameters = new List<ParameterLight>()};
                foreach ( var param in parametersGen.OrderBy(p => p.IsTypeBoolean))
                {
                    paramUser.Parameters.Add(param.ToParameterLight());   
                }
                ParamsUserModules.Add(paramUser);
            }

            //Autres modules
            foreach (var module in AccessControlService.Modules)
            {
                IModuleMetadata module1 = module;
                var parameters = DatabaseService.Service.Where<SysParametres>(p => p.IsParamUser && p.ExcludedToConfiguration == false && p.Module == (int)module1.Module).ToList();
                if (parameters.Any())
                {
                    var paramUserOther = new ParameterModule { Header = ModulesHelper.LocalizeModule(module.Module), Parameters = new List<ParameterLight>() };
                    foreach (var param in parameters.OrderBy(p => p.IsTypeBoolean))
                    {
                        //Permet de chercher la valeur utilisateur du paramétre et non juste sa valeur simple
                        param.Valeur = ParametreService.GetValueParameter(param);
                        paramUserOther.Parameters.Add(param.ToParameterLight());
                    }
                    ParamsUserModules.Add(paramUserOther);
                }
            }
        }

        /// <summary>
        /// Charge les paramètres systeme
        /// </summary>
        private void LoadParamsSystem()
        {
            if (AccessControlService.IsAuthorizedFunction(RightsService.GetIdentifiantRight((int)RightsEnum.ViewParametersSystem, TypeModulesEnum.Core)))
            {
                ParamsSystemModules = new Collection<ParameterModule>();
                var parameters =
                    DatabaseService.Service.Where<SysParametres>(
                        p => p.IsParamUser == false && p.ExcludedToConfiguration == false).ToList();
                if (parameters.Any())
                {
                    foreach (var paramsGroup in parameters.GroupBy(p => p.Module))
                    {
                        var paramsSystem = new ParameterModule() {Parameters = new List<ParameterLight>()};
                        IGrouping<int, SysParametres> @group = paramsGroup;
                        var modules = AccessControlService.Modules.Where(m => (int) m.Module == @group.Key);
                        paramsSystem.Header = ModulesHelper.LocalizeModule(modules.Any() ? modules.First().Module : TypeModulesEnum.Core);

                        foreach (var parameter in paramsGroup.OrderBy(p => p.IsTypeBoolean))
                        {
                            paramsSystem.Parameters.Add(parameter.ToParameterLight());
                        }

                        if (paramsSystem.Parameters.Any())
                        {
                            ParamsSystemModules.Add(paramsSystem);
                        }
                    }
                }
            }
        }

        /// <summary>
        /// Chargement des utilisateurs
        /// </summary>
        private void LoadUsers()
        {
            if (AccessControlService.IsAuthorizedFunction(RightsService.GetIdentifiantRight((int)RightsEnum.ViewAssociationRights, TypeModulesEnum.Core)))
            {
                Utilisateurs = DatabaseService.Service.GetAll<SysUtilisateur>().ToList();
            }
        }

        /// <summary>
        /// Chargement des groupes
        /// </summary>
        private void LoadGroupes()
        {
            if (AccessControlService.IsAuthorizedFunction(RightsService.GetIdentifiantRight((int)RightsEnum.ViewAssociationRights, TypeModulesEnum.Core)))
            {
                //Chargement des utilisateurs - A l'exception de l'administrateur qui ne peut être modifié
                Groupes = DatabaseService.Service.GetAll<SysGroupe>().ToList();
            }
        }
        #endregion
    }
}
